import re
import amara

def fixup_namespaces(node):
    """
    reduces namespace clutter in documents by looking for duplicate namespace
    declarations and preferring those set as document prefixes
    """
    doc = node.rootNode
    nss = dict(zip(doc.xmlns_prefixes.values(), doc.xmlns_prefixes.keys()))
    if node.namespaceURI in nss:
        node.xmlnsPrefix = nss[node.namespaceURI]
        node.nodeName = node.prefix and node.prefix + ':' + node.localName or node.localName
    for child in node.xml_xpath(u'*'): fixup_namespaces(child)
    return


from Ft.Xml.XPath import Conversions
def quick_xml_multiscan(source, field, xpath_filter=None, display=None, count=1, **kwargs):
    """
    Expanded version of amara.binderytools.quick_xml_scan
    Scan through an XML file to extract the first N occurrences of single field,
        without loading more of the file than needed to find the data.  Returns a
        list of tuples ((node.namespaceURI, node.localName), value) representing the
        qualified name of the matched node and the result value (always a Unicode object)
    field - a Uncode object representing an XSLT pattern
    filter - an optional XPath expression for filtering results from the pattern
    display - an optional XPath expression indicating what value to display, with the matching node from the pattern as the context
    count - number of results to return
    """
    result = []
    found = 0
    nodes = amara.pushbind(source, field, **kwargs)
    for node in nodes:
        if not xpath_filter or node.xml_xpath(filter):
            if display:
                #Print specified expression
                value = Conversions.StringValue(node.xml_xpath(display))
            else:
                value = Conversions.StringValue(node)
            result.append(((node.namespaceURI, node.localName), value))
            found += 1
            if found == count: break
    return result


class node_wrapper:
    def __init__(self, node):
        self.node = node
        return

    def __iter__(self):
        return iter([self.node.xml()])


#Based on Ian Bicking algorithm in PEP 333
def get_base_url(environ):
    from urllib import quote
    url = environ['wsgi.url_scheme']+'://'

    if environ.get('HTTP_HOST'):
        url += environ['HTTP_HOST']
    else:
        url += environ['SERVER_NAME']

        if environ['wsgi.url_scheme'] == 'https':
            if environ['SERVER_PORT'] != '443':
               url += ':' + environ['SERVER_PORT']
        else:
            if environ['SERVER_PORT'] != '80':
               url += ':' + environ['SERVER_PORT']

    url += quote(environ.get('SCRIPT_NAME', '')) + '/'
    return url


class Url(object):
    def __init__(self, regex):
        self.regex = regex
        self.m = re.compile(self.regex)

    def match(self, url):
        m = self.m.match(url)
        if m:
            return m.groupdict()
        else:
            return None

class UrlDispatch(object):
    def __init__(self, urls):
        self.urls = []
        for url in urls:
            self.urls.append((url[1], Url(url[0])))

    def match(self, path):
        for func, url in self.urls:
            match = url.match(path)
            if match is not None:
                return func, match
        return None, None


def web_trigger(environ, iri):
    """
    See http://notes.4suite.org/Bright_Content%3aDesign%3aWeb_Triggers
    """
    return environ['paste.recursive.include'](iri).body

